<script lang="ts" setup>
  import { ElMessage } from 'element-plus'
  import type { UploadInstance, UploadFile } from 'element-plus'
  import { Plus } from '@element-plus/icons-vue'
  import { useUserStore } from '@/store/modules/user'
  import { baseURL } from '@/config'

  interface IFile {
    uid: number
    name: string
    url: string
    status: string
  }

  const props = defineProps({
    modelValue: {
      type: [String, Array],
      default: '',
    },
    limit: {
      type: Number,
      default: () => 1,
    },
    accept: {
      type: String,
      default: () => 'image',
    },
    multiple: {
      type: Boolean,
    },
    showFileList: {
      type: Boolean,
      default: () => false,
    },
    type: {
      type: String,
      default: () => 'image',
    },
  })
  const emit = defineEmits(['change', 'update:modelValue'])

  const userStore = useUserStore()
  const { token } = storeToRefs(userStore)
  const upload = reactive({
    action: `${baseURL}/zgyp-system/api/v1/files`,
    headers: {
      Authorization: `Bearer ${token._object.token}`,
    },
  })
  const uploadRef = ref<UploadInstance>()
  const fileList = ref<IFile[]>([])
  const selectFileLength = ref<number>(0)
  const uploadPool = ref<string[]>([])

  defineExpose({
    uploadRef,
  })

  const ACCEPT_TYPE = {
    image: 'image/*',
    excel: '.xlsx,.xls,.csv',
    audio: 'audio/*',
  }
  const allowAccept = computed(() => {
    return props.accept in ACCEPT_TYPE
      ? ACCEPT_TYPE[props.accept]
      : props.accept || ''
  })

  watch(
    () => props.modelValue,
    (val: string[] | string) => {
      let lists = []
      if (typeof val === 'string' && val) {
        lists = [val]
      } else if (Array.isArray(val) && val.length) {
        lists = val
      } else {
        lists = []
      }
      const res = [...lists]
      if (res.length) {
        fileList.value = res.map((url: string) => {
          const uid = new Date().getTime()
          return {
            uid,
            status: 'success',
            name: window.decodeURI(url.slice(url.lastIndexOf('/') + 1)),
            url,
          }
        })
      }
    },
    {
      immediate: true,
      deep: true,
    }
  )

  const handleExceed = () => {
    ElMessage.warning('超过最大上传数量，请重新选择')
  }

  const handleBeforeUpload = () => {
    selectFileLength.value = selectFileLength.value + 1
  }

  const handleRemove = (uploadFile: UploadFile) => {
    const { url } = uploadFile || {}
    const i = fileList.value.findIndex((item) => item.url === url)
    if (i >= 0) {
      fileList.value.splice(i, 1)
      const value = props.multiple ? [...fileList.value.map((v) => v.url)] : ''
      emit('change', value)
      emit('update:modelValue', value)
    }
  }

  const handleSuccess = (res: any) => {
    const { url } = res.data
    uploadPool.value.push(url)
    if (uploadPool.value.length < selectFileLength.value) return
    const value = props.multiple
      ? [...fileList.value.map((v) => v.url), ...uploadPool.value]
      : url
    emit('change', value)
    emit('update:modelValue', value)
    uploadRef.value.clearFiles()
    uploadPool.value = []
    selectFileLength.value = 0
  }

  const dialogImageUrl = ref<string>('')
  const dialogVisible = ref<boolean>(false)
  const handlePreview = (uploadFile: any) => {
    dialogImageUrl.value = uploadFile.url
    dialogVisible.value = true
  }
</script>

<template>
  <el-upload
    ref="uploadRef"
    class="custom-uploader"
    :file-list="fileList"
    :action="upload.action"
    :headers="upload.headers"
    list-type="picture-card"
    :limit="limit"
    :accept="allowAccept"
    :multiple="multiple"
    :show-file-list="showFileList"
    :on-success="handleSuccess"
    :on-exceed="handleExceed"
    :on-remove="handleRemove"
    :before-upload="handleBeforeUpload"
    :on-preview="handlePreview"
  >
    <el-icon>
      <Plus />
    </el-icon>
  </el-upload>

  <el-dialog v-model="dialogVisible" title="图片预览" top="50px">
    <img w-full :src="dialogImageUrl" alt="Preview Image" style="width: 100%" />
  </el-dialog>
</template>

<style scoped>
  .custom-uploader.hide /deep/ .el-upload--picture-card {
    transition: 0s;
    display: none;
  }
  .custom-uploader /deep/ .el-upload-list__item {
    transition: none !important;
  }
</style>
